/*  Marx libvlc 0.9.0 Wrapper v0.0.2 - Alpha Release
    
    
    Copyright (C) 2008  Marx Bitware <support@marxbitware.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

using System;
using System.Runtime.InteropServices;
using System.IO;

namespace Marx_libvlc_wrapper
{
    #region Handle for libvlc_media_player_handle

    public class Marx_libvlc_media_player_handle : SafeHandle
    {
        public Marx_libvlc_media_player_handle()
            : base(IntPtr.Zero, true)
        { }

        public override bool IsInvalid
        {
            get { return handle == IntPtr.Zero; }
        }

        protected override bool ReleaseHandle()
        {
            if (!IsInvalid)
            {
                libvlc_media_player_release(this);
                handle = IntPtr.Zero;
            }
            return true;
        }

        protected override void Dispose(bool disposing)
        {
            ReleaseHandle();
            base.Dispose(disposing);
        }

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_release(Marx_libvlc_media_player_handle libvlc_media_player_handle);
    }

    #endregion

    public class Marx_libvlc_media_player
    {
        private Marx_libvlc_media_player_handle libvlc_media_player_handle;

        #region Constructor

        /// <summary>
        /// Create an instance of the media player
        /// </summary>
        /// <param name="libvlc_handle"></param>
        public Marx_libvlc_media_player(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex)
        {
            libvlc_media_player_handle = libvlc_media_player_new(libvlc_core_handle, ref ex);
        }

        /// <summary>
        /// Create an instance of the media player from a media instance
        /// </summary>
        /// <param name="libvlc_media_handle"></param>
        public Marx_libvlc_media_player(Marx_libvlc_media_handle libvlc_media_handle, ref libvlc_exception_struct ex)
        {
            libvlc_media_player_handle = libvlc_media_player_new_from_media(libvlc_media_handle, ref ex);
        }

        #endregion

        #region Properties

        /// <summary>
        /// Returns a Handle to the Media Player Instance
        /// </summary>
        public Marx_libvlc_media_player_handle Handle
        {
            get
            {
                return libvlc_media_player_handle;
            }
        }
 
        #endregion

        #region Methods

        #region libvlc_media_player methods

        public void retain()
        {
            libvlc_media_player_retain(libvlc_media_player_handle);
        }

        public void set_media(Marx_libvlc_media_handle libvlc_media_handle, ref libvlc_exception_struct ex)
        {
            libvlc_media_player_set_media(libvlc_media_player_handle, libvlc_media_handle, ref ex);
        }

        public Marx_libvlc_media_handle get_media(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_get_media(libvlc_media_player_handle, ref ex);
        }

        public void play(ref libvlc_exception_struct ex)
        {
            libvlc_media_player_play(libvlc_media_player_handle, ref ex);
        }

        public void pause(ref libvlc_exception_struct ex)
        {
            libvlc_media_player_pause(libvlc_media_player_handle, ref ex);
        }

        public void stop(ref libvlc_exception_struct ex)
        {
            libvlc_media_player_stop(libvlc_media_player_handle, ref ex);
        }

        public Int64 get_length(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_get_length(libvlc_media_player_handle, ref ex);
        }

        public Int64 get_time(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_get_time(libvlc_media_player_handle, ref ex);
        }

        public void set_time(Int64 time, ref libvlc_exception_struct ex)
        {
            libvlc_media_player_set_time(libvlc_media_player_handle, time, ref ex);
        }

        public float get_position(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_get_position(libvlc_media_player_handle, ref ex);
        }

        public void set_position(float position, ref libvlc_exception_struct ex)
        {
            libvlc_media_player_set_position(libvlc_media_player_handle, position, ref ex);
        }

        public void set_chapter(int chapter, ref libvlc_exception_struct ex)
        {
            libvlc_media_player_set_chapter(libvlc_media_player_handle, chapter, ref ex);
        }

        public int get_chapter(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_get_chapter_count(libvlc_media_player_handle, ref ex);
        }

        public int will_play(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_will_play(libvlc_media_player_handle, ref ex);
        }

        public float get_rate(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_get_rate(libvlc_media_player_handle, ref ex);
        }

        public void set_rate(ref libvlc_exception_struct ex, float rate)
        {
            libvlc_media_player_set_rate(libvlc_media_player_handle, rate, ref ex);
        }

        public float get_fps(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_get_fps(libvlc_media_player_handle, ref ex);
        }

        public int has_vout(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_has_vout(libvlc_media_player_handle, ref ex);
        }

        public int is_seekable(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_is_seekable(libvlc_media_player_handle, ref ex);
        }

        public int can_pause(ref libvlc_exception_struct ex)
        {
            return libvlc_media_player_can_pause(libvlc_media_player_handle, ref ex);
        }

        public void set_drawable(IntPtr hDT, ref libvlc_exception_struct ex)
        {
            libvlc_media_player_set_drawable(libvlc_media_player_handle, hDT, ref ex);
        }

        #endregion

        #region libvlc_video methods

        public void toggle_fullscreen(ref libvlc_exception_struct ex)
        {
            libvlc_toggle_fullscreen(libvlc_media_player_handle, ref ex);
        }

        public void set_fullscreen(ref libvlc_exception_struct ex)
        {
            libvlc_set_fullscreen(libvlc_media_player_handle, ref ex);
        }

        public int get_fullscreen(ref libvlc_exception_struct ex)
        {
            return libvlc_get_fullscreen(libvlc_media_player_handle, ref ex);
        }

        public int video_get_height(ref libvlc_exception_struct ex)
        {
            return libvlc_video_get_height(libvlc_media_player_handle, ref ex);
        }

        public int video_get_width(ref libvlc_exception_struct ex)
        {
            return libvlc_video_get_width(libvlc_media_player_handle, ref ex);
        }

        public string video_get_aspect_ratio(ref libvlc_exception_struct ex)
        {
            return libvlc_video_get_aspect_ratio(libvlc_media_player_handle, ref ex);
        }

        public void video_set_aspect_ratio(string ratio, ref libvlc_exception_struct ex)
        {
            libvlc_video_set_aspect_ratio(libvlc_media_player_handle, ratio, ref ex);
        }

        public int video_get_spu(ref libvlc_exception_struct ex)
        {
            return libvlc_video_get_spu(libvlc_media_player_handle, ref ex);
        }

        public void video_set_spu(int spu, ref libvlc_exception_struct ex)
        {
            libvlc_video_set_spu(libvlc_media_player_handle, spu, ref ex);
        }

        public int video_set_subtitle_file(string file, ref libvlc_exception_struct ex)
        {
            return libvlc_video_set_subtitle_file(libvlc_media_player_handle, file, ref ex);
        }

        public string video_get_crop_geometry(ref libvlc_exception_struct ex)
        {
            return libvlc_video_get_crop_geometry(libvlc_media_player_handle, ref ex);
        }

        public void video_set_crop_geometry(string geometry, ref libvlc_exception_struct ex)
        {
            libvlc_video_set_crop_geometry(libvlc_media_player_handle, geometry, ref ex);
        }

        public void toggle_teletext(ref libvlc_exception_struct ex)
        {
            libvlc_toggle_teletext(libvlc_media_player_handle, ref ex);
        }

        public int video_get_teletext(ref libvlc_exception_struct ex)
        {
            return libvlc_video_get_teletext(libvlc_media_player_handle, ref ex);
        }

        public void video_set_teletext(int page, ref libvlc_exception_struct ex)
        {
            libvlc_video_set_teletext(libvlc_media_player_handle, page, ref ex);
        }

        public void video_take_snapshot(string filepath, uint width, uint height, ref libvlc_exception_struct ex)
        {
            libvlc_video_take_snapshot(libvlc_media_player_handle, filepath, width, height, ref ex);
        }

        public int video_destroy(ref libvlc_exception_struct ex)
        {
            return libvlc_video_destroy(libvlc_media_player_handle, ref ex);
        }

        public void video_resize(int width, int height, ref libvlc_exception_struct ex)
        {
            libvlc_video_resize(libvlc_media_player_handle, width, height, ref ex);
        }

        public int video_reparent(IntPtr hDT, ref libvlc_exception_struct ex)
        {
            return libvlc_video_reparent(libvlc_media_player_handle, hDT, ref ex);
        }

        public void video_set_parent(Marx_libvlc_core_handle libvlc_core_handle, IntPtr hDT, ref libvlc_exception_struct ex)
        {
            libvlc_video_set_parent(libvlc_core_handle, hDT, ref ex);
        }

        public IntPtr video_get_parent(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex)
        {
            return libvlc_video_get_parent(libvlc_core_handle, ref ex);
        }

        public void video_set_size(Marx_libvlc_core_handle libvlc_core_handle, int width, int height, ref libvlc_exception_struct ex)
        {
            libvlc_video_set_size(libvlc_core_handle, width, height, ref ex);
        }

        #endregion

        #region libvlc_audio methods

        public void audio_toggle_mute(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex)
        {
            libvlc_audio_toggle_mute(libvlc_core_handle, ref ex);
        }

        public int audio_get_mute(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex)
        {
            return libvlc_audio_get_mute(libvlc_core_handle, ref ex);
        }

        public void audio_set_mute(Marx_libvlc_core_handle libvlc_core_handle, int mutestatus, ref libvlc_exception_struct ex)
        {
            libvlc_audio_set_mute(libvlc_core_handle, mutestatus, ref ex);
        }

        public int audio_get_volume(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex)
        {
            return libvlc_audio_get_volume(libvlc_core_handle, ref ex);
        }

        public void audio_set_volume(Marx_libvlc_core_handle libvlc_core_handle, int volume, ref libvlc_exception_struct ex)
        {
            libvlc_audio_set_volume(libvlc_core_handle, volume, ref ex);
        }

        public int audio_get_track_count(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex)
        {
            return libvlc_audio_get_track_count(libvlc_media_player_handle, ref ex);
        }

        public void audio_set_track(Marx_libvlc_media_player_handle libvlc_media_player_handle, int track, ref libvlc_exception_struct ex)
        {
            libvlc_audio_set_track(libvlc_media_player_handle, track, ref ex);
        }

        public int audio_get_channel(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex)
        {
            return libvlc_audio_get_channel(libvlc_core_handle, ref ex);
        }

        public void audio_set_channel(Marx_libvlc_core_handle libvlc_core_handle, int channel, ref libvlc_exception_struct ex)
        {
            libvlc_audio_set_channel(libvlc_core_handle, channel, ref ex);
        }
 
        #endregion

        #endregion

        #region DLL Imports

        [DllImport("libvlc")]
        private static extern Marx_libvlc_media_player_handle libvlc_media_player_new(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern Marx_libvlc_media_player_handle libvlc_media_player_new_from_media(Marx_libvlc_media_handle libvlc_media_handle, ref libvlc_exception_struct ex);

        #region libvlc_media_player

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_retain(Marx_libvlc_media_player_handle libvlc_media_player_handle);

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_set_media(Marx_libvlc_media_player_handle libvlc_media_player_handle, Marx_libvlc_media_handle libvlc_media_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern Marx_libvlc_media_handle libvlc_media_player_get_media(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        //TODO: ADD libvlc_media_player_event_manager

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_play(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_pause(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_stop(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_set_drawable(Marx_libvlc_media_player_handle libvlc_media_player_handle, IntPtr Hwnd, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern Int64 libvlc_media_player_get_length(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern Int64 libvlc_media_player_get_time(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_set_time(Marx_libvlc_media_player_handle libvlc_media_player_handle, Int64 time, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern float libvlc_media_player_get_position(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_set_position(Marx_libvlc_media_player_handle libvlc_media_player_handle, float position, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_set_chapter(Marx_libvlc_media_player_handle libvlc_media_player_handle, int chapter, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_media_player_get_chapter(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_media_player_get_chapter_count(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_media_player_will_play(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern float libvlc_media_player_get_rate(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_media_player_set_rate(Marx_libvlc_media_player_handle libvlc_media_player_handle, float rate, ref libvlc_exception_struct ex);

        //TODO: ADD libvlc_media_player_get_state

        [DllImport("libvlc")]
        private static extern float libvlc_media_player_get_fps(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_media_player_has_vout(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_media_player_is_seekable(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_media_player_can_pause(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        #endregion

        #region Marx_libvlc_video

        [DllImport("libvlc")]
        private static extern void libvlc_toggle_fullscreen(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_set_fullscreen(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_get_fullscreen(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_video_get_height(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_video_get_width(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern string libvlc_video_get_aspect_ratio(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_video_set_aspect_ratio(Marx_libvlc_media_player_handle libvlc_media_player_handle, string ratio, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_video_get_spu(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_video_set_spu(Marx_libvlc_media_player_handle libvlc_media_player_handle, int spu, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_video_set_subtitle_file(Marx_libvlc_media_player_handle libvlc_media_player_handle, string file, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern string libvlc_video_get_crop_geometry(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_video_set_crop_geometry(Marx_libvlc_media_player_handle libvlc_media_player_handle, string geom, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_toggle_teletext(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_video_get_teletext(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_video_set_teletext(Marx_libvlc_media_player_handle libvlc_media_player_handle, int page, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_video_take_snapshot(Marx_libvlc_media_player_handle libvlc_media_player_handle, string filepath, uint width, uint height, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_video_destroy(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_video_resize(Marx_libvlc_media_player_handle libvlc_media_player_handle, int width, int height, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_video_reparent(Marx_libvlc_media_player_handle libvlc_media_player_handle, IntPtr Hwnd, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_video_set_parent(Marx_libvlc_core_handle libvlc_core_handle, IntPtr Hwnd, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern IntPtr libvlc_video_get_parent(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_video_set_size(Marx_libvlc_core_handle libvlc_core_handle, int width, int height, ref libvlc_exception_struct ex);

        #endregion

        #region Marx_libvlc_audio

        [DllImport("libvlc")]
        private static extern void libvlc_audio_toggle_mute(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_audio_get_mute(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_audio_set_mute(Marx_libvlc_core_handle libvlc_core_handle, int mutestatus, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_audio_get_volume(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_audio_set_volume(Marx_libvlc_core_handle libvlc_core_handle, int volume, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_audio_get_track_count(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_audio_get_track(Marx_libvlc_media_player_handle libvlc_media_player_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_audio_set_track(Marx_libvlc_media_player_handle libvlc_media_player_handle, int track, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern int libvlc_audio_get_channel(Marx_libvlc_core_handle libvlc_core_handle, ref libvlc_exception_struct ex);

        [DllImport("libvlc")]
        private static extern void libvlc_audio_set_channel(Marx_libvlc_core_handle libvlc_core_handle, int channel, ref libvlc_exception_struct ex);

        #endregion

        #endregion
    }
}
